package org.example.service;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.example.domain.*;
import org.example.utils.HttpResult;
import org.example.utils.HttpUtils;
import org.example.utils.WxAccessTokenClient;
import org.example.utils.XmlBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;

import static org.example.config.Constant.*;

/**
 * 微信公众号需要有客服权限，需要企业认证
 */
//@Service
@Slf4j
public class ChatServiceBackup {

    private static final ConcurrentHashMap<String, User> map = new ConcurrentHashMap<>();

    private static volatile boolean runningFlag = false;

    @Autowired
    WxAccessTokenClient wxAccessTokenClient;

    @Autowired
    Executor executor;

    @Value("${proxy.flag:false}")
    String usingProxy;
    @Value("${proxy.ip:127.0.0.1}")
    String proxyIp;

    @Value("${proxy.port:10809}")
    int proxyPort;

    @Value(("${chatgptToken: }"))
    String chatgptToken;

    @Value("${wxToken: }")
    String token;

    @Value("${wxEncodingAESKey: }")
    String wxEncodingAESKey;

    public void receiveFromWx(String body, HttpServletResponse response) throws IOException {
        WxInputMessage input = (WxInputMessage) XmlBuilder.xmlStrToObject(WxInputMessage.class, body);
        if (input == null) {
            log.info("数据解析失败！");
            response.getWriter().println("数据解析失败!");
            return;
        }
        log.info(input.toString());
        if (!"text".equals(input.getMsgType())) {
            log.info("不支持的消息类型！");
            response.getWriter().println("不支持的消息类型!");
            return;
        }
        if (runningFlag) {
            //限流
            log.info("限流！");
            response.getWriter().println("限流!");
            return;
        }
        //异步执行
        executor.execute(() -> {
            synchronized (this) {
                try {
                    runningFlag = true;
                    ChatResponse result = chatgptApi1(WxRequest.builder().openID(input.getFromUserName()).content(input.getContent()).build());
                    //发送微信客服消息
                    StringBuilder bu = new StringBuilder();
                    List<ChatResponse.Choice> list = result.getChoices();
                    for (ChatResponse.Choice choice : list) {
                        bu.append(choice.getMessage().getContent());
                    }
                    /*http请求方式: POST https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN
                    {
                        "touser":"OPENID",
                        "msgtype":"text",
                        "text":
                        {
                             "content":"Hello World"
                        }
                    }*/
                    String token = wxAccessTokenClient.getAccessToken();
                    HttpUtils.postApplicationJson(WX_SEND_URL + token, null,
                            WxSend.builder().touser(input.getFromUserName()).msgtype("text").text(
                                    WxSend.Message.builder().content(bu.toString()).build()).build(),
                            Map.class, null);
                } catch (Exception e) {
                    log.error("未知错误", e);
                } finally {
                    runningFlag = false;
                }
            }
        });
        response.getWriter().println("");
    }


    public synchronized ChatResponse chatgptApi1(WxRequest request) {
        String openID = request.getOpenID();
        User user = map.get(openID);
        ChatMessage chatMessage = new ChatMessage();
        chatMessage.setRole(ChatMessage.ROLE_USER);
        chatMessage.setContent(request.getContent());
        if (user == null) {
            user = new User();
            user.setUniCode(openID);
            map.put(openID, user);
        }
        user.getMessages().add(chatMessage);
        ChatRequest chatRequest = new ChatRequest();
        chatRequest.setModel(GPT_3_5_TURBO);
        chatRequest.setMessages(user.getMessages());
        Proxy proxy = null;
        if (usingProxy.equals("true")) {
            proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyIp, proxyPort));
        }
        Map<String, String> reqHeaderApi1 = new HashMap<>();
        reqHeaderApi1.put("Authorization", "Bearer " + chatgptToken);
        HttpResult<ChatResponse> httpResult = HttpUtils.postApplicationJson(API_URL1, reqHeaderApi1, chatRequest, ChatResponse.class, proxy);
        if (httpResult.getStatusCode() != 200 || httpResult.getResult() == null || CollectionUtils.isEmpty(httpResult.getResult().getChoices())) {
            user.clearMessages();
            log.info("报错清除历史消息:" + openID);
            return null;
        }
        //保存此轮回复
        ChatResponse result = httpResult.getResult();
        List<ChatResponse.Choice> choices = result.getChoices();
        if (!CollectionUtils.isEmpty(choices)) {
            for (ChatResponse.Choice choice : choices) {
                ChatMessage message = choice.getMessage();
                user.getMessages().add(message);
            }
        }
        return result;
    }

    public void tokenCheck(HttpServletRequest request, HttpServletResponse response) throws IOException {
        /*
         * 验证消息的确来自微信服务器
         * 1）将token、timestamp、nonce三个参数进行字典序排序
         * 2）将三个参数字符串拼接成一个字符串进行sha1加密
         * 3）开发者获得加密后的字符串可与signature对比，标识该请求来源于微信
         * */
        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");
        log.info("signature=" + signature + ",timestamp=" + timestamp + ",nonce=" + nonce + ",echostr=" + echostr);
        String[] arr = {token, timestamp, nonce};
        Arrays.sort(arr);
        StringBuilder sb = new StringBuilder();
        for (String a : arr) {
            sb.append(a);
        }
        String sha1Msg = DigestUtils.sha1Hex(sb.toString().getBytes());
        if (signature.equals(sha1Msg)) {
            log.info("验证成功！");
            response.getWriter().println(echostr);
        }
    }

}
